package com.elitel.frame.web.serverinfocustom.service.impl;

import com.elitel.common.utils.SysUserUtils;
import com.elitel.frame.web.cfgsqlext.dao.CfgSqlExtDao;
import com.elitel.frame.web.cfgsqlext.entity.CfgSqlExt;
import com.elitel.frame.web.cfgsqlextlog.dao.CfgSqlExtLogDao;
import com.elitel.frame.web.cfgsqlextlog.entity.CfgSqlExtLog;
import com.elitel.frame.web.cfgsqlqueryfield.dao.CfgSqlQueryFiledDao;
import com.elitel.frame.web.cfgsqlqueryfield.entity.CfgSqlQueryField;
import com.elitel.frame.web.cfgsqlshowfield.dao.CfgSqlShowFiledDao;
import com.elitel.frame.web.cfgsqlshowfield.entity.CfgSqlShowField;
import com.elitel.frame.web.common.idworker.IdWorker;
import com.elitel.frame.web.serverinfo.dto.ServerConfigDTO;
import com.elitel.frame.web.serverinfo.dto.ServerInfoDTO;
import com.elitel.frame.web.serverinfo.dto.ServerQueryFieldDTO;
import com.elitel.frame.web.serverinfo.dto.ServerShowFieldDTO;
import com.elitel.frame.web.serverinfocustom.dto.SqlServerInfoDTO;
import com.elitel.frame.web.serverinfocustom.service.SererInfoCustomService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author m
 */
@Service
public class SqlServerInfoService implements SererInfoCustomService {

    @Resource
    private CfgSqlExtDao cfgSqlExtDao;

    @Resource
    private CfgSqlExtLogDao cfgSqlExtLogDao;

    @Resource
    private CfgSqlQueryFiledDao cfgSqlQueryFiledDao;

    @Resource
    private CfgSqlShowFiledDao cfgSqlShowFiledDao;

    @Override
    public void save(ServerInfoDTO dto) throws Exception {
        CfgSqlExt cfgSqlExt = this.getCfgSqlExt(dto);
        String dtSql = cfgSqlExt.getDtSql();
        if (dtSql != null && !dtSql.isEmpty()) {
            dtSql = decrypt(dtSql);
            cfgSqlExt.setDtSql(dtSql);
        } else {
            throw new RuntimeException("sql 不能为空");
        }
        // 保存 cfg_extsql
        CfgSqlExt dbSqlExt = cfgSqlExtDao.queryById(cfgSqlExt.getGuid());
        if (dbSqlExt == null) {
            cfgSqlExt.setCreatedate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            cfgSqlExt.setCreateuser(SysUserUtils.getLoginAccount());
            cfgSqlExtDao.insert(cfgSqlExt);
        } else {
            cfgSqlExtDao.update(cfgSqlExt);
        }
        // 保存sql日志
        CfgSqlExtLog cfgSqlExtLog = new CfgSqlExtLog();
        cfgSqlExtLog.setExtsqlLogId(IdWorker.createStrId());
        cfgSqlExtLog.setServicecode(dto.getBasicConfig().getServiceCode());
        cfgSqlExtLog.setServicename(cfgSqlExt.getServicename());
        cfgSqlExtLog.setDtDbKey(cfgSqlExt.getDtDbKey());
        cfgSqlExtLog.setDtSql(dtSql);
        cfgSqlExtLog.setCreatedUser(SysUserUtils.getLoginAccount());
        cfgSqlExtLog.setCreatedTime(new Date());
        cfgSqlExtLogDao.insert(cfgSqlExtLog);


        // 保存 base_sqlfieldtype
        List<CfgSqlQueryField> queryFieldList = this.getCfgSqlQueryFieldList(dto);
        cfgSqlQueryFiledDao.deleteByServerId(dto.getBasicConfig().getServiceCode());
        if (!CollectionUtils.isEmpty(queryFieldList)) {
            cfgSqlQueryFiledDao.insertBatch(queryFieldList);
        }

        // 保存 base_sqlconfig
        List<CfgSqlShowField> sqlShowFieldList = this.getSqlShowFieldList(dto);
        cfgSqlShowFiledDao.deleteByServerId(dto.getBasicConfig().getServerId());
        if (!CollectionUtils.isEmpty(sqlShowFieldList)) {
            cfgSqlShowFiledDao.insertBatch(sqlShowFieldList);
        }

    }

    public static String decrypt(String encryptedText) throws Exception {
        String key = "d3a7f4c81e6b2095f12e8d472bcf891a";
        // 截取前32字符作为IV（与JS逻辑一致）
        String ivString = key.substring(0, 16);

        // 转换密钥和IV为字节数组
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        byte[] ivBytes = ivString.getBytes(StandardCharsets.UTF_8);

        // 处理Base64加密数据
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);

        // 初始化AES解密器
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

        // 执行解密并返回UTF8字符串
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    private List<CfgSqlShowField> getSqlShowFieldList(ServerInfoDTO dto) {
        final String serviceCode = dto.getBasicConfig().getServiceCode();
        List<ServerShowFieldDTO> showFieldList = dto.getShowFieldList();

        return showFieldList.stream().map(showField -> {
            CfgSqlShowField res = new CfgSqlShowField();
            res.setGuid(IdWorker.createStrId());
            res.setServiceid(serviceCode);
            res.setFiledname(showField.getFieldName());
            res.setFieldcaption(showField.getFieldName());
            res.setIsqueryfield(0);
            res.setShoworder(showField.getFieldOrder());
            res.setQueryorder(showField.getDataOrder());
            String fieldType = showField.getFieldType();
            if (fieldType == null) {
                fieldType = "string";
            }
            fieldType = fieldType.toLowerCase();
            switch (fieldType) {
                case "string":
                    res.setShowtype(2);
                    break;
                case "date":
                    res.setShowtype(1);
                    break;
                default:
                    res.setShowtype(0);
                    break;
            }
            res.setDtConfigId("");
            res.setCreatedate(LocalDateTime.now());
            res.setCreateuser(SysUserUtils.getLoginAccount());
            res.setRemark(showField.getRemark());
            return res;
        }).collect(Collectors.toList());
    }


    private CfgSqlExt getCfgSqlExt(ServerInfoDTO dto) {
        SqlServerInfoDTO successor = dto.getSuccessor(SqlServerInfoDTO.class);
        ServerConfigDTO basicConfig = dto.getBasicConfig();
        CfgSqlExt cfgSqlExt = new CfgSqlExt();
        cfgSqlExt.setGuid(basicConfig.getServiceCode());
        cfgSqlExt.setServicename(basicConfig.getServerName());
        cfgSqlExt.setDtDbKey(basicConfig.getDbKey());
        cfgSqlExt.setDtSql(successor.getSql());
        cfgSqlExt.setDtRemark(basicConfig.getRemark());
        cfgSqlExt.setSyscatch(0);
        // 0-freemaker 1-ognl
        String sql = successor.getSql();
        if (sql.contains("#if")) {
            cfgSqlExt.setParamtype(0);
        } else {
            cfgSqlExt.setParamtype(1);
        }
        cfgSqlExt.setCatchtime(0);
        cfgSqlExt.setIspagination(Integer.parseInt(basicConfig.getPaginationFlag() == null ? "1" : basicConfig.getPaginationFlag()));
        cfgSqlExt.setTimeDelay(0);
        cfgSqlExt.setResponsemode(0);
        return cfgSqlExt;
    }


    private List<CfgSqlQueryField> getCfgSqlQueryFieldList(ServerInfoDTO dto) {
        ServerConfigDTO basicConfig = dto.getBasicConfig();
        List<ServerQueryFieldDTO> queryFieldList = dto.getQueryFieldList();
        final String serviceCode = basicConfig.getServiceCode();
        List<CfgSqlQueryField> resList = queryFieldList.stream().map(queryField -> {
            CfgSqlQueryField query = new CfgSqlQueryField();
            query.setGuid(IdWorker.createStrId());
            query.setServiceid(serviceCode);
            query.setFieldname(queryField.getFieldName());
            query.setFieldjavatype(queryField.getFieldType());
            query.setCreatedate(LocalDateTime.now());
            query.setNote(queryField.getFieldName());
            return query;

        }).collect(Collectors.toList());
        return resList;
    }


    /**
     * 根据id查询服务自定义配置信息
     *
     * @param serverId
     * @return
     */
    @Override
    public Map<String, Object> selectByServerId(String serverId) {
        CfgSqlExt cfgSqlExt = cfgSqlExtDao.queryById(serverId);
        HashMap<String, Object> resMap = new HashMap<>();
        if (cfgSqlExt != null) {
            resMap.put("sql", cfgSqlExt.getDtSql());
        }
        return resMap;
    }
}
